<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">
<html>

<head>
<meta http-equiv="Content-Language" content="en-us">
<title>Child scripts</title>
<link rel="stylesheet" type="text/css" href="../style.css">
</head>

<body>

<div align="center">
<table class=allEncompassingTable >
 <tr>
  <td >
<p><a href="../index.html" TARGET="_top"><img src="images/homeImg.png"></a></p>



<h1>Child scripts <img src="images/childScripts1.jpg"></h1>

<p>A child script is a <a href="simulationScripts.htm">simulation script</a>. CoppeliaSim supports an unlimited number of child scripts per <a href="scenes.htm">scene</a>. Each child script represents a small collection of routines written in <a href="scripts.htm">Lua</a> allowing handling a particular function in a <a href="simulation.htm">simulation</a>. Child scripts are attached to (or <em>associated with</em>) <a href="objects.htm">scene objects</a>, and they can be easily recognized from their script icon in the <a href="userInterface.htm#SceneHierarchy">scene hierarchy</a>:</p>

<p align=center><img src="images/childScripts0.jpg"></p>
<p class=imageLabel>[A child script associated with object <em>youBot</em>]</p>

<p>Double-clicking the script icon allows opening the <a href="scriptEditor.htm">script editor</a>. You can change properties of a given script, or associate it with another object via the <a href="scriptProperties.htm">script dialog</a>. You can attach a new child script to an object by selecting the object, then navigating to [menu bar --&gt; Add --&gt; Associated child script]. </p>

<p>  A child script's association with a scene object has important and positive consequences: </p>
<li><strong>Very good portability</strong>: child scripts will be saved/loaded together with their associated object. Using child scripts, you are able to create extremely portable code and simulation <a href="models.htm">models</a> that do not need to rely on any system specific plugin. A fully functional model can be contained in a single file (usable without modification across various platforms), which is not the case when relying on <a href="plugins.htm">plugins</a> for model control. Additionally, and for the same reason, models relying on child scripts require no maintenance over time (e.g. a new OS version will not require you to adjust portions of code or recompilation, as you might have to do when using <a href="plugins.htm">plugins</a>).</li>
<li><strong>Inherent scalability</strong>: if an object that has an attached child script is duplicated, its child script will also be duplicated. The duplicated child script's content will be identical to the original child script's content, however, the duplicated child script will <em>know</em> that is was duplicated and redirect object access correctly (e.g. if the original child script is accessing &quot;robot&quot;, then the duplicated child script will automatically append a name suffix to &quot;robot&quot; in order to access the duplicated &quot;robot&quot; and not the original one). Refer to the section on <a href="accessingGeneralObjects.htm">accessing general-type objects programmatically</a> for more details. The automatic name suffix adjustment allows duplicating objects and behavior without having to rewrite / adjust any code.</li>

<li><strong>No conflict between different model versions</strong>: if you modify the child script of a given model (e.g. to customize it to your needs), this will have no consequence on other similar models. This is a much more critical aspect when relying on <a href="plugins.htm">plugins</a> instead of child scripts for model control: indeed, with plugins you always run the risk of having conflicts with previous plugin versions.</li>

<li><strong>Very easy synchronization with the simulation loop</strong>: child scripts can run <a href="#threaded">threaded</a> and <a href="#nonThreaded">non-threaded</a> (see further down). And even the threaded version of child scripts can be easily synchronized with the simulation loop, which represents a powerful feature.</li>

<p> Child scripts can be of two different types: <a href="#nonThreaded">non-threaded child scripts</a> or <a href="#threaded">threaded child scripts</a>:<br>
</p>
<p align=center><img src="images/childScripts1.jpg"></p>
<p class=imageLabel>[non-threaded child script icon (left), threaded child script icon (right)]</p>
<br>

<table class=subsectionTable><tr class=subsectionTd><td class=subsectionTd>
<a name="nonThreaded"></a>Non-threaded child scripts
</td></tr></table> 


<p>Non-threaded child scripts should contain a collection of system callback functions. Those should not be blocking. This means that every time they are called, they should perform some task and then return control. If control is not returned, then the whole <a href="simulation.htm">simulation</a> halts. Non-threaded child script functions are called by the <a href="mainScript.htm">main script</a> at least twice per simulation step from the main script's actuation and sensing functions. The system will also call other system callback functions where appropriate (e.g. during child script initialization, clean-up, etc). Non-threaded child scripts should always be chosen over <a href="#threaded">threaded child scripts</a> whenever possible.</p>
<p>Non-threaded child scripts follow a <a href="scriptExecution.htm">precise calling or execution order</a>: by default, child scripts are called starting with leaf objects (or childless objects), and ending with root objects (or parentless objects). The command <a href="regularApi/simHandleChildScripts.htm">sim.handleChildScripts</a>, called from the default <a href="mainScript.htm">main script</a>, handles the most important system callback functions: imagine an example of a simulation model representing an automatic door: a proximity sensor in the front and the back allows detecting an approaching person. When the person is close enough, the door opens automatically. Following code shows a typical non-threaded child script  illustrating above example:<br>
</p>

<a name="nonThreadedChildScriptExample"></a>
<pre class=lightRedBox>
function <strong>sysCall_init</strong>()
    sensorHandleFront=sim.getObjectHandle("DoorSensorFront")
    sensorHandleBack=sim.getObjectHandle("DoorSensorBack")
    motorHandle=sim.getObjectHandle("DoorMotor")
end

function <strong>sysCall_actuation</strong>()
    resF=sim.readProximitySensor(sensorHandleFront) 
    resB=sim.readProximitySensor(sensorHandleBack)
    if ((resF>0)or(resB>0)) then
        sim.setJointTargetVelocity(motorHandle,-0.2)
    else
        sim.setJointTargetVelocity(motorHandle,0.2)
    end
end</pre>

<p>
A non-threaded child script tyically is segmented into a collection of system callback functions, the most important ones are:
</p>

<li><strong>the initialization function</strong>: <strong>sysCall_init</strong>. This system callback function is the only one that is not optional. It will be executed just one time (the first time the child script is called). This can be at the beginning of a simulation, but also in the middle of a simulation: remember that objects associated with child scripts can be copy/pasted into a <a href="scenes.htm">scene</a> at any time, also when a simulation is running. Usually you would put some initialization code as well as handle retrieval in this part.<br>
</li>

<li><strong>the actuation function</strong>: <strong>sysCall_actuation</strong>. This part will be executed in each simulation step, during the actuation phase of a simulation step. Refer to the <a href="mainScript.htm">main script</a> default code for more details about the actuation phase, but typically, you would do some actuation in this part (no sensing).<br>
</li>

<li><strong>the sensing function</strong>: <strong>sysCall_sensing</strong>. This part will be executed in each simulation step, during the sensing phase of a simulation step. Refer to the <a href="mainScript.htm">main script</a> default code for more details about the sensing phase, but typically, you would only do sensing in this part (no actuation).<br>
</li>


<li><strong>the restoration function</strong>: <strong>sysCall_cleanup</strong>. This part will be executed one time just before a simulation ends, or before the script is destroyed. </li>

<p>There are however many more system callback functions a non-threaded child script can use to react to various events:</p>
<pre class=lightRedBox>
function <strong>sysCall_init</strong>() -- not optional!!
    -- Put some initialization code here
end

function <strong>sysCall_actuation</strong>()
    -- Put some actuation code here
end

function <strong>sysCall_sensing</strong>()
    -- Put some sensing code here
end

function <strong>sysCall_cleanup</strong>()
    -- Put some restoration code here
end

function <strong>sysCall_dynCallback</strong>(inData)
    -- See the <a href="dynCallbackFunctions.htm">dynamics callback function</a> section in the user manual for details about the input argument
end

function <strong>sysCall_jointCallback</strong>(inData)
    -- See the <a href="jointCallbackFunctions.htm">joint callback function</a> section in the user manual for details about input/output arguments
    return outData
end

function <strong>sysCall_contactCallback</strong>(inData)
    -- See the <a href="contactCallbackFunction.htm">contact callback function</a> section in the user manual for details about input/output arguments
    return outData
end

function <strong>sysCall_vision</strong>(inData)
    -- See the <a href="visionCallbackFunctions.htm">vision callback function</a> section in the user manual for details about input/output arguments
    return outData
end

function <strong>sysCall_trigger</strong>(inData)
    -- See the <a href="triggerCallbackFunctions.htm">trigger callback function</a> section in the user manual for details about input/output arguments
    return outData
end

function <strong>sysCall_beforeCopy</strong>(inData)
    for key,value in pairs(inData.objectHandles) do
        print("Object with handle "..key.." will be copied")
    end
end

function <strong>sysCall_afterCopy</strong>(inData)
    for key,value in pairs(inData.objectHandles) do
        print("Object with handle "..key.." was copied")
    end
end

function <strong>sysCall_afterCreate</strong>(inData)
    for key,value in pairs(inData.objectHandles) do
        print("Object with handle "..value.." was created")
    end
end

function <strong>sysCall_beforeDelete</strong>(inData)
    for key,value in pairs(inData.objectHandles) do
        print("Object with handle "..key.." will be deleted")
    end
    -- inData.allObjects indicates if all objects in the scene will be deleted
end

function <strong>sysCall_afterDelete</strong>(inData)
    for key,value in pairs(inData.objectHandles) do
        print("Object with handle "..key.." was deleted")
    end
    -- inData.allObjects indicates if all objects in the scene were deleted
end

function <strong>sysCall_suspend</strong>()
    -- Simulation is about to be suspended
end

function <strong>sysCall_suspended</strong>()
    -- Simulation is suspended
end

function <strong>sysCall_resume</strong>()
    -- Simulation is about to be resumed
end</pre>

<br>
<br>
<br>






<table class=subsectionTable><tr class=subsectionTd><td class=subsectionTd>
<a name="threaded"></a>Threaded child scripts
</td></tr></table> 


<p>Threaded child scripts are scripts that will launch in a thread. The launch (and resume) of threaded child scripts is handled by the default <a href="mainScript.htm">main script</a> code, via the <a href="regularApi/simLaunchThreadedChildScripts.htm">sim.launchThreadedChildScripts</a> and <a href="regularApi/simResumeThreads.htm">sim.resumeThreads</a> functions. Launch/resume of threaded child scripts is executed in a <a href="scriptExecution.htm">precise order</a>. When a threaded child script's execution is still underway, it will not be launched a second time. When a threaded child script ended, it can be relaunched only if the <strong>execute once</strong> item in the <a href="scriptProperties.htm">script properties</a> is unchecked. A threaded child script icon in the <a href="userInterface.htm#SceneHierarchy">scene hierarchy</a> is displayed in light blue instead of white to indicate that it will be launched in a thread.<br>
</p>

<p>Threaded child scripts have several weaknesses compared to non-threaded child scripts if not programmed appropriately: they are  more resource-intensive, they can waste some processing time, and they can be a little bit less responsive to a simulation stop command.<br>
</p>

<p>Following shows a typical threaded child script code, which is however not perfect since <strong>it is wasting precious computation time</strong> in the loop (the code handles the automatic sliding doors from above's example):<br>
</p>

<pre class=lightRedBox>
function <strong>sysCall_threadmain</strong>()
    -- Put some initialization code here:
    sensorHandleFront=sim.getObjectHandle("DoorSensorFront")
    sensorHandleBack=sim.getObjectHandle("DoorSensorBack")
    motorHandle=sim.getObjectHandle("DoorMotor")
    
    -- Here we execute the regular thread code:
    while sim.getSimulationState()~=sim.simulation_advancing_abouttostop do
        resF=sim.readProximitySensor(sensorHandleFront)
        resB=sim.readProximitySensor(sensorHandleBack)
        if ((resF>0)or(resB>0)) then
            sim.setJointTargetVelocity(motorHandle,-0.2)
        else
            sim.setJointTargetVelocity(motorHandle,0.2)
        end
        -- this loop wastes precious computation time since we should only read new
        -- values when the simulation time has changed (i.e. in next simulation step).
    end
end

function <strong>sysCall_cleanup</strong>()
	-- Put some clean-up code here:
end</pre>

<p>A threaded child script typically is segmented into a collection of system callback functions, the main ones being:<br>
</p>


<li><strong>the main function: sysCall_threadmain</strong>: this system callback function is the only one that is not optional. It will be executed when the thread starts, until shortly before the thread ends. This can be at the beginning of a simulation, but also in the middle of a simulation: remember that objects associated with child scripts can be copy/pasted into a scene at any time, also when a simulation is running. Usually you would put some initialization code as well as the main loop in this part: the code in the loop is in charge of handling a specific part of a simulation (e.g. handle the automatic sliding door). In above specific example, the loop is wasting precious computation time and is running asynchronously with the main simulation loop. See further down for a better example.<br>
</li>

<li><strong>the restoration function: sysCall_cleanup</strong>: this part will be executed one time just before a simulation ends, or before the thread ends. <br>
</li>

<p>CoppeliaSim uses threads to mimic the behavior of coroutines, instead of using them <em>traditionally</em>, which allows for a great deal of flexibility and control: by default a threaded child script will execute for about 1-2 milliseconds before automatically switching to another thread. This default behavior can be changed with the <a href="regularApi/simSetThreadSwitchTiming.htm">sim.setThreadSwitchTiming</a> or <a href="regularApi/simSetThreadAutomaticSwitch.htm">sim.setThreadAutomaticSwitch</a>. Once the current thread was switched, it will resume execution in next simulation pass (i.e. at a time currentTime+simulationTimeStep). The thread switching is automatic (occurs after the specified time), but the <a href="regularApi/simSwitchThread.htm">sim.switchThread</a> command allows to shorten that time when needed. Using above three commands, a perfect synchronization with the main simulation loop can be achieved. Following code (handling the automatic sliding doors from above's example) shows child script synchronization with the main simulation loop:<br>
</p>

<pre class=lightRedBox>
function <strong>sysCall_threadmain</strong>()
    -- Put some initialization code here:
    <strong>sim.setThreadAutomaticSwitch</strong>(false) -- disable automatic thread switches
    sensorHandleFront=sim.getObjectHandle("DoorSensorFront")
    sensorHandleBack=sim.getObjectHandle("DoorSensorBack")
    motorHandle=sim.getObjectHandle("DoorMotor")
    
    -- Here we execute the regular thread code:
    while sim.getSimulationState()~=sim.simulation_advancing_abouttostop do
        resF=sim.readProximitySensor(sensorHandleFront)
        resB=sim.readProximitySensor(sensorHandleBack)
        if ((resF>0)or(resB>0)) then
            sim.setJointTargetVelocity(motorHandle,-0.2)
        else
            sim.setJointTargetVelocity(motorHandle,0.2)
        end
        <strong>sim.switchThread</strong>() -- <strong>Explicitely switch to another thread now!</strong>
        -- <strong>from now on, above loop is executed once in each simulation step.</strong>
        -- <strong>this way you do not waste precious computation time and run synchronously.</strong>
    end
end

function <strong>sysCall_cleanup</strong>()
    -- Put some clean-up code here
end</pre>

<p>Above while loop will now execute exactly once for each main simulation loop and not waste time reading sensors states again and again for same simulation times. By default, threads always resume when the main script calls <em>sim.resumeThreads(sim.scriptthreadresume_default)</em>. If you need to make sure your thread runs only while the main script is in the sensing phase, you can resquedule the thread's resume location with the API function <a href="regularApi/simSetThreadResumeLocation.htm">sim.setThreadResumeLocation</a>.<br>
</p>

<p>The coroutine-like behavior of CoppeliaSim's threads cannot be distinguished from regular threads, with the exception that if an external command (for example socket communication commands provided by Lua libraries) is blocking, then CoppeliaSim will also appear as blocking. In that case, a non-blocking section can be defined as in following example:<br>
</p>

<pre class=lightRedBox>
<strong>sim.setThreadIsFree</strong>(true) -- Start of the non-blocking section

http = require("socket.http")
print(http.request("http://www.google.com")) -- this command may take several seconds to execute

<strong>sim.setThreadIsFree</strong>(false) -- End of the non-blocking section</pre>

<p>While in a non-blocking section, avoid at all cost calling sim-functions. Never forget to close the blocking section otherwise CoppeliaSim might hang or run much slowlier. Also refer to the <a href="apiFunctionListCategory.htm#threadRelatedFunctionality">thread-related functions</a> and to the <a href="apiFunctionListCategory.htm#blockingFunctions">blocking functions</a> for more details on thread operation in CoppeliaSim.</p>
<p>Some operation should not be interrupted in order to execute correctly (imagine moving several objects in a loop). In that case, you can temporarily forbid thread switches with the <a href="regularApi/simSetThreadAutomaticSwitch.htm">sim.setThreadAutomaticSwitch</a> function.</p>

<p>There are a few other system callback functions a threaded child script can use to react to various events:</p>
<pre class=lightRedBox>
function <strong>sysCall_threadmain</strong>() -- not optional!!
    -- Initialization and main loop
end

function <strong>sysCall_cleanup</strong>()
    -- Put some restoration code here
end

function <strong>sysCall_vision</strong>(inData)
    -- See the <a href="visionCallbackFunctions.htm">vision callback function</a> section in the user manual for details about input/output arguments
    return outData
end

function <strong>sysCall_trigger</strong>(inData)
    -- See the <a href="triggerCallbackFunctions.htm">trigger callback function</a> section in the user manual for details about input/output arguments
    return outData
end</pre>




<br>
<h3 class=recommendedTopics>Recommended topics</h3>
<li><a href="mainScript.htm">The main script</a></li>
<li><a href="scriptExecution.htm">Script execution order</a></li>
<br>
<br>
 </tr>
</table> 
</div>  
  
  
</body>

</html>
